#include "mem.h"
#include "types.h"
#include "serial.h"
#include "util.h"
#include "config.h"

int load_memory(char *optstr, u32 addr) 
{
	u32 read;

	if(MyStrCmp(optstr, "-l", 2)) {
		read = *((u32 *)addr);
		printk("%08x\n", read);
	} else if(MyStrCmp(optstr, "-h", 2)) { 
		read = *((u16 *)addr);
		printk("%04x\n", read);
	} else if(MyStrCmp(optstr, "-b", 2)) { 
		read = *((u8 *)addr);
		printk("%02x\n", read);
	} else {
		printk("Invalid option string : -l, -h -b are valid\n");
	}
	return 1;
}

int store_memory(char *optstr, u32 addr, u32 val) 
{
	if(MyStrCmp(optstr, "-l", 2)) {
		*((u32 *)addr) = (u32)val;
	} else if(MyStrCmp(optstr, "-h", 2)) { 
		*((u16 *)addr) = (u16)val;
	} else if(MyStrCmp(optstr, "-b", 2)) { 
		*((u8 *)addr) = (u8)val;
	} else {
		printk("Invalid option string : -l, -h -b are valid\n");
	}
	return 1;
}

void DumpMem(u32* address, u32 length)
{
	u32 i;
	u32 PrintAddress;

	PrintAddress = (((u32)address)/16)*16;

	printk("\n           ");
	printk("00000000 00000004 00000008 0000000c\n");

	for(i=0; i<= (length-1)/16; i++){
		printk("0x%08x %08x %08x %08x %08x\n", PrintAddress, *((u32*)(PrintAddress)), *((u32*)(PrintAddress+4)), *((u32*)(PrintAddress+8)), *((u32*)(PrintAddress+12)));
		PrintAddress += 16;
	}
}

void CmpMem(u32 address1, u32 address2, u32 length)
{
	u32 equal;
	u32 i;

	equal=1;
	for(i=0;i<length;i+=4){
		if((*(u32*)((u32)address1+i))!=(*(u32*)((u32)address2+i))){
			printk("%08x : %08x, %08x : %08x\n",(u32)address1+i, *(u32*)((u32)address1+i), (u32)address2+i, *(u32*)((u32)address2+i));
			equal=0;
		}
	}

	if(equal==1) printk("Equal data\n");
}

/*
  Warning : pass of this test does not guarantee the complete operation of the SDRAM

  just copy a data to the address and check if the data is correct
  need more read/write pattern to test the SDRAM completely
*/
void ram_test(u32* address, int LengthInMB)
{
	u32 TestStartAddress;
	u32 i;

	TestStartAddress = (((u32)address)/4)*4;
	for(i = TestStartAddress;i < TestStartAddress + LengthInMB*0x100000L; i+=4){  
		if((i>=RAM_START + RAM_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START) && (i<= RAM_START + RAM_STACK_END_OFFSET_FROM_RAM_START)){ 
			/* as for boot code area, do not test 
			 * Even this cannot protect the boot code against the aliasing. so be careful.
			 */ 
		} else {  
			(*(u32*)i) = i+1;
		}
	}
	for(i = TestStartAddress;i < TestStartAddress + LengthInMB*0x100000L; i+=4){  
		if((i>=RAM_START + RAM_BOOT_LOADER_AREA_START_OFFSET_FROM_RAM_START) && (i<= RAM_START + RAM_STACK_END_OFFSET_FROM_RAM_START)){ 
			/* as for boot code area, do not test */ 
		} else {  
			if((*(u32*)i) != i+1){
				printk("RAM Error @ 0x%08x\n", i);
				return;
			}
		}
	}

	printk("RAM Test OK\n");
}
